package com.niu.filter;

import com.alibaba.fastjson.JSONObject;
import com.niu.pojo.MyResult;
import com.niu.utils.MyJwtUtils;
import com.niu.utils.MyThreadLocalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @Author 鹅鹅鹅
 * @Version 1.0.0
 * @Date 2025/7/17 21:54
 * @Description 登录时进行校验
 */
@WebFilter(urlPatterns = "/*")
@Component
public class MyLoginFilter implements Filter {

    @Autowired
    private MyJwtUtils myJwtUtils;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        /**
         * 1. 获取路径, 若去登录就放行, 不是登录就要进行验证
         * 2. 获取请求头的token 数据
         * 3. 对数据进行校验
         * 4. 如果不合法, 返回错误状态对象
         */
        // 放行前过滤
        // 1. 获取请求路径
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        // 对请求路径进行判断, 若是登录就放行, 不是登录就进行过滤
        String uri = request.getRequestURI(); // 获取请求的资源路径

        if (!"/login".equals(uri)){ // 不是登录请求
            // 2. 获取请求头的token 数据
            String token = request.getHeader("token");
            // 3. 对数据进行校验
            Map<String, Object> map = myJwtUtils.parseJWT(token);
            // 3.1 不合法或令牌过期, 不可通过, 且响应错误信息
            if (map == null){
                // 将错误信息转换成统一响应格式返回给前端
                MyResult<Object> result = MyResult.error("NOT_LOGIN");
                // 将result 返回给前端, 需要转换成json 格式, 因为该类不是 controller层, 需要我们自己手动转格式, 且手动将数据返回
                String jsonString = JSONObject.toJSONString(result);
                // 给前端响应
                HttpServletResponse response = (HttpServletResponse) servletResponse;
                response.getWriter().println(jsonString);
                return;
            }
            // 3.2 合法map 使用本地线程存入ThreadLocal 中, 以便后续重复利用
            MyThreadLocalUtils.setValue(map);
        }

        // 放行
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
